package com.wenx.v3system.config;

import com.wenx.v3secure.user.UserDetail;
import com.wenx.v3system.modular.cloud.service.SysUserPermissionService;
import com.wenx.v3system.modular.platform.service.PlatformUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 自定义JWT认证转换器
 * 将JWT中的用户信息和权限转换为UserDetail对象，确保与LoginUser工具类兼容
 * 在认证成功后从数据库补充完整的用户角色权限信息
 * 
 * @author wenx
 */
@Component
public class CustomJwtConverter implements Converter<Jwt, AbstractAuthenticationToken> {

    private static final Logger log = LoggerFactory.getLogger(CustomJwtConverter.class);

    private final SysUserPermissionService sysUserPermissionService;
    private final PlatformUserService platformUserService;

    public CustomJwtConverter(SysUserPermissionService sysUserPermissionService,
                             PlatformUserService platformUserService) {
        this.sysUserPermissionService = sysUserPermissionService;
        this.platformUserService = platformUserService;
    }

    @Override
    public AbstractAuthenticationToken convert(Jwt jwt) {
        log.debug("CustomJwtConverter.convert() 被调用，JWT subject: {}, claims: {}", jwt.getSubject(), jwt.getClaims());
        
        // 检查是否为客户端凭据流程的token（没有用户信息，只有客户端信息）
        if (isClientCredentialsToken(jwt)) {
            log.debug("检测到客户端凭据token，clientId: {}", jwt.getSubject());
            // 对于客户端凭据流程，使用客户端ID作为principal
            String clientId = jwt.getSubject();
            Collection<GrantedAuthority> authorities = extractAuthorities(jwt);
            log.debug("客户端凭据token权限: {}", authorities);

            return new UsernamePasswordAuthenticationToken(clientId, null, authorities);
        }
        
        // 对于用户token，从JWT中提取用户信息并创建UserDetail对象
        UserDetail userDetail = createUserDetailFromJwt(jwt);
        log.debug("从JWT创建UserDetail: userId={}, username={}, isPlatformUser={}", 
                userDetail.getId(), userDetail.getUsername(), userDetail.isPlatformUser());
        
        // 验证用户ID是否有效
        if (userDetail.getId() == null) {
            log.warn("用户ID为空，无法从数据库加载权限信息，使用JWT中的基础权限");
            Collection<GrantedAuthority> basicAuthorities = extractAuthorities(jwt);
            log.debug("基础权限: {}", basicAuthorities);
            return new UsernamePasswordAuthenticationToken(userDetail, null, basicAuthorities);
        }
        
        // 从数据库加载并补充完整的用户角色权限信息
        Set<String> authoritySet = new HashSet<>();

        if (userDetail.isPlatformUser()) {
            log.debug("加载平台用户权限，userId: {}", userDetail.getId());
            List<String> permissions = platformUserService.getUserPermissions(userDetail.getId());
            List<String> roles = platformUserService.getUserRoles(userDetail.getId());

            log.debug("平台用户权限查询结果 - permissions: {}, roles: {}", permissions, roles);

            if (permissions != null) {
                authoritySet.addAll(permissions);
            }

            if (roles != null) {
                roles.forEach(role -> authoritySet.add("ROLE_" + role));
            }
        } else {
            log.debug("加载系统用户权限，userId: {}", userDetail.getId());
            Set<String> permissions = sysUserPermissionService.getUserPermissions(userDetail.getId());
            Set<Long> roleIds = sysUserPermissionService.getUserRoles(userDetail.getId());

            log.debug("系统用户权限查询结果 - permissions: {}, roleIds: {}", permissions, roleIds);

            if (permissions != null) {
                authoritySet.addAll(permissions);
            }

            if (roleIds != null) {
                roleIds.forEach(roleId -> authoritySet.add("ROLE_" + roleId));
            }
        }
        
        if (authoritySet.isEmpty()) {
            log.debug("权限集合为空，添加默认ROLE_USER权限");
            authoritySet.add("ROLE_USER");
        }
        
        log.debug("最终权限集合: {}", authoritySet);
        userDetail.setAuthoritySet(authoritySet);
        return new UsernamePasswordAuthenticationToken(userDetail, null, userDetail.getAuthorities());
    }

    /**
     * 检查是否为客户端凭据流程的token
     */
    private boolean isClientCredentialsToken(Jwt jwt) {
        Object userId = jwt.getClaim("userId");
        Object username = jwt.getClaim("username");
        return userId == null && username == null;
    }
    
    /**
     * 从JWT中创建UserDetail对象
     */
    private UserDetail createUserDetailFromJwt(Jwt jwt) {
        UserDetail userDetail = new UserDetail();
        
        log.debug("开始从JWT创建UserDetail，JWT claims: {}", jwt.getClaims());
        
        // 设置基本用户信息
        Object userIdClaim = jwt.getClaim("userId");
        log.debug("JWT中的userId claim: {} (类型: {})", userIdClaim, userIdClaim != null ? userIdClaim.getClass().getSimpleName() : "null");
        
        if (userIdClaim instanceof Number) {
            userDetail.setId(((Number) userIdClaim).longValue());
            log.debug("解析userId为Number: {}", userDetail.getId());
        } else if (userIdClaim instanceof String) {
            try {
                userDetail.setId(Long.parseLong((String) userIdClaim));
                log.debug("解析userId为String转Long: {}", userDetail.getId());
            } catch (NumberFormatException e) {
                log.warn("无法解析userId: {}", userIdClaim);
            }
        } else {
            log.warn("JWT中未找到有效的userId字段或格式不正确");
        }
        
        String username = jwt.getClaim("username");
        log.debug("JWT中的username: {}", username);
        userDetail.setUsername(username);

        // 判断用户类型：优先使用JWT中的isPlatformUser字段，否则根据username前缀判断
        Boolean isPlatformUserClaim = jwt.getClaim("isPlatformUser");
        boolean isPlatformUser;
        if (isPlatformUserClaim != null) {
            isPlatformUser = isPlatformUserClaim;
            log.debug("从JWT claim获取用户类型: isPlatformUser={}", isPlatformUser);
        } else {
            // 兼容旧版本：根据username前缀判断
            isPlatformUser = username != null && username.startsWith("platform:");
            log.debug("根据username前缀判断用户类型 - username: {}, isPlatformUser: {}", username, isPlatformUser);
        }
        userDetail.setPlatformUser(isPlatformUser);
        
        // 设置JWT中的基础权限集合（后续会被数据库权限覆盖）
        Set<String> authoritySet = extractAuthoritySet(jwt);
        userDetail.setAuthoritySet(authoritySet);
        log.debug("从JWT提取的基础权限: {}", authoritySet);
        
        // 设置账户状态（默认为可用）
        userDetail.setAccountNonExpired(true);
        userDetail.setAccountNonLocked(true);
        userDetail.setCredentialsNonExpired(true);
        userDetail.setEnabled(true);
        
        log.debug("UserDetail创建完成: userId={}, username={}, isPlatformUser={}, authorities={}", 
                userDetail.getId(), userDetail.getUsername(), userDetail.isPlatformUser(), authoritySet);
        
        return userDetail;
    }

    /**
     * 从JWT中提取权限信息
     */
    private Collection<GrantedAuthority> extractAuthorities(Jwt jwt) {
        Set<String> authoritySet = extractAuthoritySet(jwt);
        return authoritySet.stream()
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
    }
    
    /**
     * 从JWT中提取权限集合
     */
    private Set<String> extractAuthoritySet(Jwt jwt) {
        Set<String> authorities = new HashSet<>();
        
        log.debug("开始从JWT提取权限信息");
        
        // 从JWT的authorities声明中获取权限列表
        Object authoritiesClaim = jwt.getClaim("authorities");
        log.debug("JWT中的authorities claim: {} (类型: {})", authoritiesClaim, authoritiesClaim != null ? authoritiesClaim.getClass().getSimpleName() : "null");
        
        if (authoritiesClaim instanceof List<?> authoritiesList) {
            log.debug("从authorities列表中提取权限，列表大小: {}", authoritiesList.size());
            authoritiesList.stream()
                    .filter(String.class::isInstance)
                    .map(String.class::cast)
                    .peek(auth -> log.debug("添加authorities权限: {}", auth))
                    .forEach(authorities::add);
        }
        
        // 从JWT的scope声明中获取OAuth2 scope权限
        Object scopeClaim = jwt.getClaim("scope");
        log.debug("JWT中的scope claim: {} (类型: {})", scopeClaim, scopeClaim != null ? scopeClaim.getClass().getSimpleName() : "null");
        
        if (scopeClaim instanceof List<?> scopeList) {
            // scope是数组格式
            log.debug("从scope列表中提取权限，列表大小: {}", scopeList.size());
            scopeList.stream()
                    .filter(String.class::isInstance)
                    .map(String.class::cast)
                    .map(scope -> "SCOPE_" + scope)
                    .peek(scopeAuth -> log.debug("添加scope权限: {}", scopeAuth))
                    .forEach(authorities::add);
        } else if (scopeClaim instanceof String scopeString) {
            // scope是字符串格式，用空格分隔
            log.debug("从scope字符串中提取权限: {}", scopeString);
            String[] scopes = scopeString.split(" ");
            for (String scope : scopes) {
                if (!scope.trim().isEmpty()) {
                    String scopeAuth = "SCOPE_" + scope.trim();
                    authorities.add(scopeAuth);
                    log.debug("添加scope权限: {}", scopeAuth);
                }
            }
        }
        
        log.debug("JWT权限提取完成，最终权限集合: {}", authorities);
        return authorities;
    }
}